package wang.naifei.core.utils.os.linux;/*
 * <h3>Title:SynologyService系统</h3>
 * <p>Copyright (c) 2021, wnfbx. All rights reserved.</p>
 * @author wnfbx
 */

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import wang.naifei.core.utils.FileUtils;
import wang.naifei.core.utils.StringUtils;

import java.io.*;

/**
 * <dt>Description:LinuxCommandUtil</dt>
 * <dd>Linux 原生命令操作</dd>
 *
 * @author wnfbx
 * @version 1.0 <i>2021/12/31 16:09</i>
 * @since jdk1.7+
 */
public class LinuxShellUtils {

    private static final Logger log = LoggerFactory.getLogger(LinuxShellUtils.class);

    /**
     * <dt>Description:renameAndMoveFile</dt>
     * <dd>移动并改名文件</dd>
     * <dd>author: wnfbx</dd>
     * <dd>version:1.0 <i>2022/1/12 19:13</i></dd>
     *
     * @param srcFile 源文件
     * @param tgtPath 目标路径
     * @param operate 覆盖，改名，不移动
     * @since jdk1.7+
     */
    public static void renameAndMoveFile(File srcFile, File tgtPath, RenameAndMoveOperate operate) {
        assert tgtPath != null : "target file must not be null";
        assert srcFile != null : "src file must not be null";
        if (!srcFile.isFile() || !srcFile.canRead()) {
            return;
        }
        if (operate == RenameAndMoveOperate.FALL && tgtPath.exists()) {
            return;
        }
        if (srcFile.getPath().equals(tgtPath.getPath())) {
            return;
        }
//        if (operate == RenameAndMoveOperate.AUTO_RENAME && tgtPath.exists()) { //判断新生成的文件是否存在 此处bug 导致500G、300个电影文件丢失
//            tgtPath = new File(tgtPath.getParent(), autoRenameFile(tgtPath.getName()));
//        }
        while (operate == RenameAndMoveOperate.AUTO_RENAME && tgtPath.exists()) { //判断新生成的文件是否存在
            tgtPath = FileUtils.newExistFileName(tgtPath);
        }
        String command = "mv " + srcFile.getPath() + " " + tgtPath.getPath();
        exec(command);
    }

    /**
     * <dt>Description:RenameAndMoveOperate</dt>
     * <dd>renameAndMoveFile的操作参数：覆盖，改名，不移动</dd>
     *
     * @author wnfbx
     * @version 1.0 <i>2021/12/31 16:09</i>
     * @since jdk1.7+
     */
    public enum RenameAndMoveOperate {
        OVERWRITE,  //移动并覆盖
        AUTO_RENAME, //移动并自动改名
        FALL //失败
    }

    /**
     * <dt>Description:execSafe</dt>
     * <dd>安全的执行命令</dd>
     * <dd>author: wnfbx</dd>
     * <dd>version:1.0 <i>2022/1/12 19:12</i></dd>
     *
     * @param shell 脚本
     * @since jdk1.7+
     */
    public static void execSafe(String shell) {
        if (LinuxShellHelper.isUnSafe(shell)) {
            exec(shell);
        } else {
            log.error("shell is not safe. [{}]", shell);
        }
    }

    /**
     * <dt>Description:exec</dt>
     * <dd>java 执行shell</dd>
     * <dd>author: wnfbx</dd>
     * <dd>version:1.0 <i>2022/1/12 19:11</i></dd>
     *
     * @param shells 命令
     *               Runtime.exec 通过 && 链接多个命令
     *               processBuilder 通过 cmd 或者 /bin/bash 连接多个命令
     * @since jdk1.7+
     */
    protected static void exec(String... shells) {
        Process shellProcess = null;
        try {
            if (shells.length==0){
                throw new IllegalArgumentException("shells is empty");
            }
            if(shells.length>1){
                shellProcess = new ProcessBuilder(shells).start();
            }else{
                shellProcess = Runtime.getRuntime().exec(shells[0]);
            }
            log.debug("运行脚本:{}", String.join(" ", shells));
            //必须读取执行消息
            printMsg(shellProcess);
            int exitCode = shellProcess.waitFor();
            log.debug("process completed, exit code:{}", exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (null != shellProcess) {
                shellProcess.destroy();
            }
        }
    }

    private static void printMsg(Process shellProcess) {
        try (InputStream info_s = shellProcess.getInputStream();
             InputStreamReader info_r = new InputStreamReader(info_s);
             BufferedReader shellInfoResultReader = new BufferedReader(info_r);
             InputStream err_s = shellProcess.getErrorStream();
             InputStreamReader err_r = new InputStreamReader(err_s);
             BufferedReader shellErrorResultReader = new BufferedReader(err_r);
        ) {
            String infoLine;
            while ((infoLine = shellInfoResultReader.readLine()) != null) {
                log.debug("脚本执行信息:{}", infoLine);
            }

            String errorLine;
            while ((errorLine = shellErrorResultReader.readLine()) != null) {
                log.debug("脚本错误信息:{}", errorLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
